import java.net.*;
import java.io.*;
import java.util.*;

public class NewChatServer {

   public static void main(String args[]) {

     try {
	ServerSocket ssk = new ServerSocket(2199);
	Broadcaster  bst = new Broadcaster();
	Socket sk = null;	
	while ( true ) {
	   sk = ssk.accept() ;
	   System.out.println("A connection is made!");
	   Thread t = new ServerAgent( sk , bst );
	   t.start();
	}
    } catch ( Exception e) { e.printStackTrace(); }
  }
}

class ServerAgent extends Thread { 

    Socket sk = null;
    Broadcaster bst = null;

    ObjectInputStream in = null;
    ObjectOutputStream out = null;
 
    public  ServerAgent( Socket s , Broadcaster c) {
	sk = s; bst = c;
    }

    void close() { 
	try { in.close(); out.close() ; }
	catch (Exception e) { e.printStackTrace(); }
    }

    public void run() {

     System.out.println("Server agent is running");
     try {
	in = new ObjectInputStream( sk.getInputStream() );
	out = new ObjectOutputStream( sk.getOutputStream() );
	
	bst.add( out );

	while (true ) {
		System.out.println("Server is reading from socket.");
		Object obj = in.readObject(); 
		bst.broadcast( obj ) ;
	}
     } catch (Exception e) {
	 bst.remove( out ) ;
	 close();
	// e.printStackTrace();
	}
   }
}


class Broadcaster extends Thread {

   Vector ostreams = new Vector(10);

   public Broadcaster() {}

   public void add( ObjectOutputStream out ) {
	ostreams.add(out);
	broadcast("Persons in chatroom after one joined: " + ostreams.size());
   } 

   public void remove( Object obj ) {
	boolean suc = ostreams.remove(obj);  
	if ( suc ) {
	    broadcast("Persons in chatroom after one left: " + ostreams.size());
	}
   }

   public void broadcast( Object obj ) {

     try {
	for ( int i = 0;  i < ostreams.size(); i ++ )
		((ObjectOutputStream) ostreams.get(i)).writeObject(obj);
     } catch (Exception e) { e.printStackTrace(); }
  }
}
